# -*- coding: utf-8 -*-
# @Time    :2022/3/5 20:45
# @AUTHOR  :MORAN
# @Email   :moran@maqu.com
# @File    :serializers.py
# @Software:PyCharm
from datetime import datetime
from decimal import Decimal
from random import randint

from rest_framework import serializers
from rest_framework.fields import SerializerMethodField
from rest_framework.serializers import ModelSerializer

from users.serializers import AddressSerializer
from .models import *
from django.db import transaction


class ClassificationSerializer(ModelSerializer):
    class Meta:
        model = Classification
        fields = ['id', 'name', 'parent']
        extra_kwargs = {
            'parent': {'write_only': True}
        }


class ParentClassificationSerializer(ModelSerializer):
    classification_set = ClassificationSerializer(many=True, read_only=True)

    class Meta:
        model = Classification
        fields = ['id', 'name', 'classification_set', 'parent']
        extra_kwargs = {
            'parent': {'write_only': True}
        }


class CommodityImgSerializer(ModelSerializer):
    class Meta:
        model = CommodityImg
        fields = ['src']


class CommoditySerializer(ModelSerializer):
    commodityimg_set = CommodityImgSerializer(many=True, read_only=True)

    class Meta:
        model = Commodity
        exclude = ['is_delete']


class ShoppingCartSerializer(ModelSerializer):
    class Meta:
        model = ShoppingCart
        fields = '__all__'

    commodityDetail = SerializerMethodField()

    def get_commodityDetail(self, shoppingcart):
        return CommoditySerializer(shoppingcart.commodity).data

    def validate(self, data):
        if data['number'] <= 0 or data['number'] > data['commodity'].stock:
            raise serializers.ValidationError('number error')
        return data


class OrderSerializer(ModelSerializer):
    cart = serializers.ListField(write_only=True)
    addressDetail = SerializerMethodField()

    def get_addressDetail(self, order):
        return AddressSerializer(order.address).data

    class Meta:
        model = Order
        fields = '__all__'
        read_only_fields = ['order_id', 'user', 'total_count', 'total_amount', 'status']

    def create(self, validated_data):
        # 订单编号
        user = self.context['request'].user
        order_id = datetime.now().strftime("%Y%m%d%H%M%S") + "%06d%02d" % (user.id, randint(1, 100))
        # 事务控制
        with transaction.atomic():
            # 创建保存点
            save_point = transaction.savepoint()
            # 创建订单信息
            try:
                pay_method = validated_data.get('pay_method')
                order = Order.objects.create(
                    order_id=order_id,
                    user=user,
                    address=validated_data.get('address'),
                    total_count=0,
                    total_amount=Decimal('0.0'),
                    pay_method=pay_method,
                    status=1 if pay_method == 1 else 2
                )
                # 获得购物车中选中的商品
                carts = validated_data.get('cart')
                for cart_id in carts:
                    while True:
                        cart = ShoppingCart.objects.get(id=cart_id)
                        commodity = cart.commodity
                        # 获得原有的库存与销量 方便乐观锁修改时进行检查
                        origin_stock = commodity.stock
                        origin_sales = commodity.sales
                        # 判断是否超出库存
                        if cart.number > commodity.stock:
                            raise serializers.ValidationError('库存不足')

                        # 库存操作 减少库存 增加销量
                        new_stock = origin_stock - cart.number
                        new_sales = origin_sales + cart.number
                        # commodity.save()

                        # 乐观锁 返回受影响的条数
                        res = Commodity.objects.filter(id=commodity.id, stock=origin_stock).update(stock=new_stock, sales=new_sales)
                        if not res:
                            continue

                        # 将购物车中要结算的商品保存到商品订单表
                        OrderGoods.objects.create(
                            number=cart.number,
                            price=commodity.price,
                            order=order,
                            commodity=commodity
                        )

                        # 得到商品总数和总价格
                        order.total_count += cart.number
                        order.total_amount += (commodity.price * cart.number)

                        break
                # 修改订单信息 保存订单
                order.save()
            except Exception as e:
                transaction.savepoint_rollback(save_point)  # 事务回滚
                raise serializers.ValidationError(e)
            else:
                transaction.savepoint_commit(save_point)  # 事务提交
        # 清楚购物车中已经结算的商品
        ShoppingCart.objects.filter(id__in=carts).delete()
        return order
